#include "HttpClients/HttpClient.hpp"
#include "HttpClients/HttpGlobalResource.hpp"

using namespace CppWinApi::HttpClients;

HttpClient::HttpClient()
{
    // 初始化全局资源
    HttpGlobalResource::InitResource();
    curl = ::curl_easy_init();
    // 设置接收数据回调
    ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnReceive);
}

HttpClient::~HttpClient()
{
    ::curl_easy_cleanup(curl);
    curl = nullptr;
    // 释放全局资源
    HttpGlobalResource::ReleaseResource();
}

size_t HttpClient::OnReceive(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    ((std::string *)userdata)->append(ptr, size * nmemb);
    return size * nmemb;
}

HttpResponse HttpClient::Post(const std::string url, const std::string body)
{
    return this->Request(url, HttpMethod::POST, body);
}

HttpResponse HttpClient::Get(const std::string url)
{
    return this->Request(url, HttpMethod::GET);
}

void HttpClient::SetHttpMethod(HttpMethod method)
{
    switch (method)
    {
    case HttpMethod::GET:
        curl_easy_setopt(this->curl, CURLOPT_HTTPGET, 1L);
        break;
    case HttpMethod::POST:
        curl_easy_setopt(this->curl, CURLOPT_POST, 1L);
        break;
    case HttpMethod::PUT:
        curl_easy_setopt(this->curl, CURLOPT_CUSTOMREQUEST, "PUT");
        break;
    case HttpMethod::DELETE:
        curl_easy_setopt(this->curl, CURLOPT_CUSTOMREQUEST, "DELETE");
        break;
    }
}

HttpResponse HttpClient::Request(const std::string url, HttpMethod method, std::string body)
{
    ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    // set http method
    this->SetHttpMethod(method);

    // set data to body if have any string
    if (!body.empty())
    {
        ::curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
        ::curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
    }

    ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, httpHeader.ToCurlHeaders());

    std::string data = "";
    ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);

    auto code = ::curl_easy_perform(curl);
    return HttpResponse(code, data);
}